#include "fillet_tool.h"
#include "../../layout/layout.hpp"
#include "../../undoRedo/undoRedo.hpp"
#include "../../utils/geom_cal_2d.h"
#include "../../utils/kutils.h"
#include "../../utils/render_line.h"
#include "../../utils/render_ref.h"

namespace qbe::FilletTool {
void exit(ecs::Query query, state::AllModeType enter_mode) {
  return;
  if (std::get<state::EditingModeType>(enter_mode) == state::EditingModeType::FilletTool) {

  } else {
    auto& param = query.get_resource<FilletToolModel>();
    param.is_start = false;
    auto& cell_cmd = query.get_resource<layout::CellCmd>();
    auto current_cell = cell_cmd.cell;
    auto& select_model = query.get_resource<select::SelectModel>();
    select_model.select_ele_ctrl = 0;
    select_model.is_continuous_select = false;
    // 清除选择标记
    for (auto [e] : current_cell->reg.view<select::SelectTag>().each()) {
      current_cell->reg.remove<select::SelectTag>(e);
    }
    param.arcs.clear();
    param.extend_lines.clear();
    auto& ecs_reg = query.get_reg();
    for (auto [e, node] : ecs_reg.view<FilletToolTag, vsg::ref_ptr<vsg::Switch>>().each()) {
      node->setAllChildren(false);
      node->children.clear();
    }
  }
}
void init(entt::registry& reg, ecs::Commands commands, ecs::Query query) {
  auto& state = query.get_resource<state::State>();
  state.addExitCall(state::EditingModeType::FilletTool, exit);
  for (auto [e, tran] : reg.view<render::SceneTag, vsg::ref_ptr<vsg::MatrixTransform>>().each()) {
    // 创建 Switch
    auto switchObject = vsg::Switch::create();
    tran->addChild(switchObject);
    commands.spawn(FilletToolTag{}, switchObject);
  }
}
void update(entt::registry& ecs_reg, ecs::Query query, ecs::Bus& bus, ecs::EventWriter<msg::RenderEvent> event) {
  return;
  auto& state = query.get_resource<state::State>();

  // 仅在模式执行
  if (state.getEditingMode() != state::EditingModeType::FilletTool)
    return;

  auto& param = query.get_resource<FilletToolModel>();
  auto& select_model = query.get_resource<select::SelectModel>();

  auto& axis = query.get_resource<axis::Axis>();
  auto& cell_cmd = query.get_resource<layout::CellCmd>();
  auto current_cell = cell_cmd.cell;
  auto& cell_reg = current_cell->reg;

  auto& layout_cmd = query.get_resource<layout::LayoutCmd>();

  //ESC退出逻辑
  {
    auto res = bus.receive<UiMessage::CancelDrawing>();
    if (!res.empty()) {
      //ESC退出逻辑
      param.is_start = false;
      select_model.select_ele_ctrl = 0;
      select_model.is_continuous_select = false;
      param.arcs.clear();
      param.extend_lines.clear();
      for (auto [e, node] : ecs_reg.view<FilletToolTag, vsg::ref_ptr<vsg::Switch>>().each()) {
        node->setAllChildren(false);
        node->children.clear();
      }
      // 清除选择标记
      for (auto [e] : current_cell->reg.view<select::SelectTag>().each()) {
        current_cell->reg.remove<select::SelectTag>(e);
      }
      state.switchMode(state::EditingModeType::None);
      param.select.clear();
    }
  }
  auto res = bus.receive<UiMessage::FilletToolUi_Ok>();
  if (!res.empty()) {
    for (auto [e, node] : ecs_reg.view<FilletToolTag, vsg::ref_ptr<vsg::Switch>>().each()) {
      node->setAllChildren(false);
      node->children.clear();
    }
    // 清除选择标记
    for (auto [e] : current_cell->reg.view<select::SelectTag>().each()) {
      current_cell->reg.remove<select::SelectTag>(e);
    }

    param.is_segment_mode = res[0].is_segment_mode;
    param.is_trim = res[0].is_trim;
    param.r = res[0].r;
    param.is_start = true;
    state.switchMode(state::SelectModeType::Overall);

    if (param.is_segment_mode == true)
      select_model.select_ele_ctrl = 1;
    else
      select_model.select_ele_ctrl = 2;
    select_model.is_continuous_select = true;

    for (auto [e, node] : ecs_reg.view<FilletToolTag, vsg::ref_ptr<vsg::Switch>>().each()) {
      node->setAllChildren(true);

      auto options = query.get_resource<vsg::ref_ptr<vsg::Options>>();
      std::shared_ptr<utils::TempRender::RenderLine> render_line =
          std::make_shared<utils::TempRender::RenderLine>(options, std::vector<qlib::Path::s_ptr>{});
      node->addChild(true, render_line->switchObject);
      render_line->setLayerType(vsg::vec4(1.0, 0.0, 1.0, 1.0), "B1");
      param.render_line = render_line;
    }
    bus.send<UiMessage::FilletToolUi_Close>(UiMessage::FilletToolUi_Close{});
    param.select.clear();

    for (auto [e, node] : ecs_reg.view<FilletToolTag, vsg::ref_ptr<vsg::Switch>>().each()) {
      node->setAllChildren(true);

      auto options = query.get_resource<vsg::ref_ptr<vsg::Options>>();
      std::shared_ptr<utils::TempRender::RenderLine> render_line =
          std::make_shared<utils::TempRender::RenderLine>(options, std::vector<qlib::Path::s_ptr>{});
      node->addChild(true, render_line->switchObject);
      render_line->setLayerType(vsg::vec4(1.0, 1.0, 0.0, 1.0), "B1");
      param.render_select_line = render_line;
    }
  }
  if (param.is_start == false)
    return;

  //获取undo/red0
  auto& unredoMoudel = query.get_resource<undoRedoT::UndoRedoModule>();

  std::vector<entt::entity> pre_select;
  for (auto [e] : cell_reg.view<select::HoverTag>().each()) {
    auto _ptr = cell_reg.try_get<qlib::Path::s_ptr>(e);
    if (_ptr) {
      auto line = *_ptr;
      if (param.is_segment_mode == true) {
        if (line->spine.points.size() == 2)
          pre_select.push_back(e);
      } else {
        if (line->spine.points.size() > 2)
          pre_select.push_back(e);
      }
    }
    if (pre_select.empty()) {
      current_cell->reg.remove<select::HoverTag>(e);
    }
  }

  for (auto [e] : cell_reg.view<select::SelectTag>().each()) {
    auto _ptr = cell_reg.try_get<qlib::Path::s_ptr>(e);
    if (_ptr) {
      auto line = *_ptr;
      if (param.is_segment_mode == true) {
        if (line->spine.points.size() == 2)
          param.select.push_back(e);
      } else {
        if (line->spine.points.size() > 2)
          param.select.push_back(e);
      }
    }
    current_cell->reg.remove<select::SelectTag>(e);

    std::vector<qlib::Path::s_ptr> lines;
    for (auto i : param.select) {
      lines.push_back(*(cell_reg.try_get<qlib::Path::s_ptr>(i)));
    }
    param.render_select_line->updateData(lines);
  }
  auto& hand = query.get_resource<vsg::ref_ptr<input::HandleBundle>>();

  //鼠标移动
  if (hand->mouse_move) {
    param.second_click_point.x = axis.real_x;
    param.second_click_point.y = axis.real_y;

    param.arcs.clear();
    param.extend_lines.clear();
    param.arc_dir.clear();
    for (auto [e, node] : ecs_reg.view<FilletToolTag, vsg::ref_ptr<vsg::Switch>>().each()) {
      param.render_line->setShowHide(false);
    }
    if (!pre_select.empty()) {
      auto _pre_line = cell_reg.try_get<qlib::Path::s_ptr>(pre_select[0]);
      if (_pre_line == nullptr)
        return;
      if (param.is_segment_mode == false) {
        std::vector<std::vector<qlib::Vec2d>> segments;
        auto pre_line = *_pre_line;
        for (int i = 0; i < pre_line->spine.points.size() - 2; i++) {
          std::vector<qlib::Vec2d> seg;
          seg.push_back(qlib::Vec2d(pre_line->spine.points[i].x, pre_line->spine.points[i].y));
          seg.push_back(qlib::Vec2d(pre_line->spine.points[i + 1].x, pre_line->spine.points[i + 1].y));
          seg.push_back(qlib::Vec2d(pre_line->spine.points[i + 2].x, pre_line->spine.points[i + 2].y));
          segments.push_back(seg);
        }
        for (auto&& seg : segments) {
          std::vector<qlib::Vec2d> _seg;
          _seg.push_back(seg[0]);
          _seg.push_back(seg[1]);
          _seg.push_back(seg[1]);
          _seg.push_back(seg[2]);
          calFilet(query, bus, _seg, param.r);
        }
        if (param.arcs.size() == pre_line->spine.points.size() - 2) {
          std::vector<qlib::Path::s_ptr> render_lines;
          //折线上全部能够倒角,就可视化显示
          for (auto&& line : param.extend_lines) {
            //图层编号处理
            if (param.is_trim == true) {
              /*auto line_node = dynamic_cast<LineNode*>(pre_select);
            line->m_elements[0].m_layer = line_node->m_flexpath->m_elements[0].m_layer;*/
            } else {
              //line->m_elements[0].m_layer = LayoutCtrlData::getCurrentSelectLayerNum();
            }

            render_lines.push_back(line);
          }

          for (auto&& fan : param.arcs) {
            auto line = std::make_shared<qlib::Path>();
            line->spine.points.clear();
            auto arc_points = fan->make_arc();
            for (int i = 0; i < arc_points.size(); i++) {
              line->spine.points.push_back(arc_points[i]);
            }
            //图层编号处理
            if (param.is_trim == true) {
              /*auto line_node = dynamic_cast<LineNode*>(pre_select);
            line->m_elements[0].m_layer = line_node->m_flexpath->m_elements[0].m_layer;*/
            } else {
              //line->m_elements[0].m_layer = LayoutCtrlData::getCurrentSelectLayerNum();
            }
            render_lines.push_back(line);
          }
          bus.send<qbe::UiMessage::OperatorInfoMessage>(qbe::UiMessage::OperatorInfoMessage{
              QString(QObject::tr("mode: fillet | Select object (%1; R=%2)")).arg(param.trimString()).arg(QString::number(param.r, 'f', 3))});

          param.render_line->updateData(render_lines);
          for (auto [e, node] : ecs_reg.view<FilletToolTag, vsg::ref_ptr<vsg::Switch>>().each()) {
            param.render_line->setShowHide(true);
          }
        } else {
          bus.send<qbe::UiMessage::OperatorInfoMessage>(qbe::UiMessage::OperatorInfoMessage{QObject::tr("mode: fillet | The radius is too large")});
        }
      } else {
        if (param.select.size() == 1) {
          if (param.select[0] == pre_select[0])
            return;
          param.segment.clear();
          {
            auto _line = cell_reg.try_get<qlib::Path::s_ptr>(param.select[0]);
            auto line = *_line;
            param.segment.push_back(qlib::Vec2d(line->spine.points[0].x, line->spine.points[0].y));
            param.segment.push_back(qlib::Vec2d(line->spine.points[1].x, line->spine.points[1].y));
          }

          {
            auto _line = cell_reg.try_get<qlib::Path::s_ptr>(pre_select[0]);
            auto line = *_line;
            param.segment.push_back(qlib::Vec2d(line->spine.points[0].x, line->spine.points[0].y));
            param.segment.push_back(qlib::Vec2d(line->spine.points[1].x, line->spine.points[1].y));
          }
          calFilet(query, bus, param.segment, param.r);
          {
            std::vector<qlib::Path::s_ptr> render_lines;
            for (auto&& line : param.extend_lines) {
              //图层编号处理
              if (param.is_trim == true) {
                /* auto line_node = dynamic_cast<LineNode*>(selected[0]);
                line->m_elements[0].m_layer = line_node->m_flexpath->m_elements[0].m_layer;*/
              } else {
                //line->m_elements[0].m_layer = LayoutCtrlData::getCurrentSelectLayerNum();
              }
              render_lines.push_back(line);
            }

            for (auto&& fan : param.arcs) {
              auto line = std::make_shared<qlib::Path>();
              line->spine.points.clear();
              auto arc_points = fan->make_arc();
              for (int i = 0; i < arc_points.size(); i++) {
                line->spine.points.push_back(arc_points[i]);
              }
              render_lines.push_back(line);
            }
            //图层编号处理
            if (param.is_trim == true) {
              /*auto line_node = dynamic_cast<LineNode*>(selected[0]);
                line->m_elements[0].m_layer = line_node->m_flexpath->m_elements[0].m_layer;*/
            } else {
              //line->m_elements[0].m_layer = LayoutCtrlData::getCurrentSelectLayerNum();
            }
            param.render_line->updateData(render_lines);
            for (auto [e, node] : ecs_reg.view<FilletToolTag, vsg::ref_ptr<vsg::Switch>>().each()) {
              param.render_line->setShowHide(true);
            }
          }
        }
      }
    }
  }

  //点击鼠标左键
  if (hand->mouseReleased(1)) {

    if (param.is_segment_mode == true && param.select.size() == 1) {
      param.first_click_point.x = axis.real_x;
      param.first_click_point.y = axis.real_y;
      bus.send<qbe::UiMessage::OperatorInfoMessage>(qbe::UiMessage::OperatorInfoMessage{
          QString(QObject::tr("mode: fillet | Select second object (%1; R=%2)")).arg(param.trimString()).arg(QString::number(param.r, 'f', 3))});
    }
    //折线模式
    if (param.is_segment_mode == false && param.select.size() == 1) {
      auto _pre_line = cell_reg.try_get<qlib::Path::s_ptr>(param.select[0]);
      auto line = *_pre_line;
      if (param.arcs.size() == line->spine.points.size() - 2) {
        if (param.is_trim == true) {
          auto new_line = std::make_shared<qlib::Path>();
          new_line->spine.points.clear();
          new_line->spine.points.push_back(line->spine.points[0]);
          for (int i = 0; i < param.arcs.size(); i++) {

            if (param.arc_dir[i] == true) {
              auto point_array = param.arcs[i]->make_arc();
              for (int j = 0; j < point_array.size(); j++) {
                new_line->spine.points.push_back(point_array[j]);
              }
            } else {
              auto point_array = param.arcs[i]->make_arc();
              for (int j = 0; j < point_array.size(); j++) {
                new_line->spine.points.push_back(point_array[point_array.size() - j - 1]);
              }
            }
          }
          new_line->spine.points.push_back(line->spine.points[line->spine.points.size() - 1]);
          unredoMoudel.start(current_cell);
          auto new_entity = layout_cmd.add(new_line);
          unredoMoudel.add(new_entity);
          unredoMoudel.dele(param.select[0]);
          layout_cmd.remove(param.select[0]);
          unredoMoudel.end();
          param.select.clear();
          //event.send(msg::RenderEvent{msg::RenderCode::CellUpdate});  //确定后版图更新
          layout_cmd.render_update();

        } else {
          unredoMoudel.start(current_cell);
          for (auto&& fan : param.arcs) {
            auto new_line = std::make_shared<qlib::Path>();
            new_line->spine.points.clear();
            auto arc_points = fan->make_arc();
            for (int i = 0; i < arc_points.size(); i++) {
              new_line->spine.points.push_back(arc_points[i]);
            }
            auto new_entity = layout_cmd.add(new_line);
            unredoMoudel.add(new_entity);
          }
          unredoMoudel.end();
          param.select.clear();
        }
      }
      param.arcs.clear();
      param.extend_lines.clear();
      for (auto [e, node] : ecs_reg.view<FilletToolTag, vsg::ref_ptr<vsg::Switch>>().each()) {
        param.render_line->setShowHide(false);
        param.render_select_line->setShowHide(false);
      }
      auto& event_writer = query.get_event_writer<select::Event>();
      // 清除预选标记
      for (auto [e] : cell_reg.view<select::HoverTag>().each()) {
        cell_reg.remove<select::HoverTag>(e);
      }
      for (auto [e] : cell_reg.view<select::SelectTag>().each()) {
        cell_reg.remove<select::SelectTag>(e);
      }
      event_writer.send({{select::Code::SelectCancel}});
      event_writer.send({{select::Code::HoverCancel}});
    } else if (param.select.size() == 2 && param.is_segment_mode == true && !param.arcs.empty()) {
      if (param.is_trim == true) {

        auto new_line = std::make_shared<qlib::Path>();
        new_line->spine.points.clear();
        new_line->spine.points.push_back(qlib::Vec2(param.segment[param.line_1_use_point_index].x, param.segment[param.line_1_use_point_index].y));
        for (int i = 0; i < param.arcs.size(); i++) {
          auto arc_points = param.arcs[i]->make_arc();
          if (param.r == 0) {
            new_line->spine.points.push_back(arc_points[0]);
          } else {
            if (param.arc_dir[i] == true) {
              for (int j = 0; j < arc_points.size(); j++) {
                new_line->spine.points.push_back(arc_points[j]);
              }
            } else {
              for (int j = 0; j < arc_points.size(); j++) {
                new_line->spine.points.push_back(arc_points[arc_points.size() - j - 1]);
              }
            }
          }
        }
        new_line->spine.points.push_back(qlib::Vec2(param.segment[param.line_2_use_point_index].x, param.segment[param.line_2_use_point_index].y));
        ////图层编号处理
        //auto line_node = dynamic_cast<LineNode*>(selected[0]);
        //line->m_elements[0].m_layer = line_node->m_flexpath->m_elements[0].m_layer;
        unredoMoudel.start(current_cell);
        auto new_entity = layout_cmd.add(new_line);
        layout_cmd.add(new_entity);
        unredoMoudel.add(new_entity);
        unredoMoudel.dele(param.select[0]);
        unredoMoudel.dele(param.select[1]);
        layout_cmd.remove(param.select[0]);
        layout_cmd.remove(param.select[1]);
        layout_cmd.render_update();  //确定后版图更新
        unredoMoudel.end();
        param.select.clear();
      } else {
        if (param.r == 0) {
        } else {
          unredoMoudel.start(current_cell);
          for (auto&& fan : param.arcs) {
            auto new_line = std::make_shared<qlib::Path>();
            new_line->spine.points.clear();
            auto arc_points = fan->make_arc();
            for (int i = 0; i < arc_points.size(); i++) {
              new_line->spine.points.push_back(arc_points[i]);
            }
            auto new_entity = layout_cmd.add(new_line);
            unredoMoudel.add(new_entity);
          }
          unredoMoudel.end();
          param.select.clear();
        }
      }

      param.arcs.clear();
      param.extend_lines.clear();
      for (auto [e, node] : ecs_reg.view<FilletToolTag, vsg::ref_ptr<vsg::Switch>>().each()) {
        param.render_line->setShowHide(false);
        param.render_select_line->setShowHide(false);
      }
      auto& event_writer = query.get_event_writer<select::Event>();
      // 清除预选标记
      for (auto [e] : cell_reg.view<select::HoverTag>().each()) {
        cell_reg.remove<select::HoverTag>(e);
      }
      for (auto [e] : cell_reg.view<select::SelectTag>().each()) {
        cell_reg.remove<select::SelectTag>(e);
      }
      event_writer.send({{select::Code::SelectCancel}});
      event_writer.send({{select::Code::HoverCancel}});
    }
    if (param.is_segment_mode == true && param.select.empty())
      bus.send<qbe::UiMessage::OperatorInfoMessage>(qbe::UiMessage::OperatorInfoMessage{
          QString(QObject::tr("mode: fillet | Select first object (%1; R=%2)")).arg(param.trimString()).arg(QString::number(param.r, 'f', 3))});
    if (param.is_segment_mode == false)

      bus.send<qbe::UiMessage::OperatorInfoMessage>(qbe::UiMessage::OperatorInfoMessage{
          QString(QObject::tr("mode: fillet | Select object (%1; R=%2)")).arg(param.trimString()).arg(QString::number(param.r, 'f', 3))});
  }
}
void post(entt::registry& reg, ecs::Commands commands, ecs::Query query, ecs::Bus& bus) {}

void sortInputPoints(ecs::Query query, std::vector<qlib::Vec2d>& input, qlib::Vec2d& inter_point, std::vector<qlib::Vec2d>& seg, bool& is_Inter) {
  auto& param = query.get_resource<FilletToolModel>();

  is_Inter = auxiliary::lineIntersectSeg(input[0], input[1], input[2], input[3], inter_point);
  //判断延伸后交点是否全在线段外部
  bool is_all_out = true;
  {
    if (is_all_out == true) {
      double dis_1 = (inter_point - input[0]).length();
      double dis_2 = (inter_point - input[1]).length();
      double dis = (input[0] - input[1]).length();
      double diff = abs(dis - dis_1 - dis_2);
      if (diff > 10e-5) {

      } else {
        is_all_out = false;
      }
    }

    if (is_all_out == true) {
      double dis_1 = (inter_point - input[2]).length();
      double dis_2 = (inter_point - input[3]).length();
      double dis = (input[2] - input[3]).length();
      double diff = abs(dis - dis_1 - dis_2);
      if (diff > 10e-5) {
      } else {
        is_all_out = false;
      }
    }
  }

  if (param.is_segment_mode == false || is_all_out == true) {
    double dis_1 = (inter_point - input[0]).length_sq();
    double dis_2 = (inter_point - input[1]).length_sq();
    if (dis_1 > dis_2) {
      seg.push_back(input[0]);
      param.line_1_no_use_point_index = 1;
      param.line_1_use_point_index = 0;
    } else {
      seg.push_back(input[1]);
      param.line_1_no_use_point_index = 0;
      param.line_1_use_point_index = 1;
    }

    seg.push_back(inter_point);

    double dis_3 = (inter_point - input[2]).length_sq();
    double dis_4 = (inter_point - input[3]).length_sq();
    if (dis_3 > dis_4) {
      seg.push_back(input[2]);
      param.line_2_no_use_point_index = 3;
      param.line_2_use_point_index = 2;
    } else {
      seg.push_back(input[3]);
      param.line_2_no_use_point_index = 2;
      param.line_2_use_point_index = 3;
    }
  } else {
    if (is_all_out == false) {
      {
        auto line_point_1 = qlib::Vec2d(input[0].x, input[0].y);
        auto line_point_2 = qlib::Vec2d(input[1].x, input[1].y);
        auto foot = auxiliary::GetFootOfPerpendicular(param.first_click_point, line_point_1, line_point_2);
        //判断点击点是否在选择线的内部
        bool isInternale = pointIsSegmentInternal(foot, line_point_1, line_point_2);
        if (isInternale == true) {
          double dis_1 = (line_point_1 - foot).length();
          double dis_2 = (inter_point - foot).length();
          double dis = (line_point_1 - inter_point).length();

          if (abs(dis - dis_1 - dis_2) > 10e-5) {
            //垂足点不在该线段内部
            seg.push_back(line_point_2);
            param.line_1_no_use_point_index = 0;
            param.line_1_use_point_index = 1;
          } else {
            seg.push_back(line_point_1);
            param.line_1_no_use_point_index = 1;
            param.line_1_use_point_index = 0;
          }
        } else {
          double dis_1 = (line_point_1 - inter_point).length();
          double dis_2 = (line_point_2 - inter_point).length();
          if (dis_1 < dis_2) {
            seg.push_back(line_point_2);
            param.line_1_no_use_point_index = 0;
            param.line_1_use_point_index = 1;
          } else {
            seg.push_back(line_point_1);
            param.line_1_no_use_point_index = 1;
            param.line_1_use_point_index = 0;
          }
        }
      }
      seg.push_back(inter_point);

      {
        auto line_point_1 = qlib::Vec2d(input[2].x, input[2].y);
        auto line_point_2 = qlib::Vec2d(input[3].x, input[3].y);
        auto foot = auxiliary::GetFootOfPerpendicular(param.second_click_point, line_point_1, line_point_2);

        //判断点击点是否在选择线的内部
        bool isInternale = pointIsSegmentInternal(foot, line_point_1, line_point_2);
        if (isInternale == true) {
          double dis_1 = (line_point_1 - foot).length();
          double dis_2 = (inter_point - foot).length();
          double dis = (line_point_1 - inter_point).length();

          if (abs(dis - dis_1 - dis_2) > 10e-5) {
            //垂足点不在该线段内部
            seg.push_back(line_point_2);
            param.line_2_no_use_point_index = 2;
            param.line_2_use_point_index = 3;
          } else {
            seg.push_back(line_point_1);
            param.line_2_no_use_point_index = 3;
            param.line_2_use_point_index = 2;
          }
        } else {
          double dis_1 = (line_point_1 - inter_point).length();
          double dis_2 = (line_point_2 - inter_point).length();
          if (dis_1 < dis_2) {
            seg.push_back(line_point_2);
            param.line_2_no_use_point_index = 2;
            param.line_2_use_point_index = 3;
          } else {
            seg.push_back(line_point_1);
            param.line_2_no_use_point_index = 3;
            param.line_2_use_point_index = 2;
          }
        }
      }
    }
  }
}

bool pointIsSegmentInternal(qlib::Vec2d& point, qlib::Vec2d& segment_1, qlib::Vec2d& segment_2) {
  double dis_1 = (point - segment_1).length();
  double dis_2 = (point - segment_2).length();
  double dis = (segment_1 - segment_2).length();
  if (abs(dis - dis_1 - dis_2) > 10e-5) {
    return false;
  } else {
    return true;
  }
}

void calFilet(ecs::Query query, ecs::Bus& bus, std::vector<qlib::Vec2d>& input, double r) {
  auto& param = query.get_resource<FilletToolModel>();
  std::shared_ptr<double> slope_1 = auxiliary::getSlope(input[0], input[1]);
  std::shared_ptr<double> slope_2 = auxiliary::getSlope(input[2], input[3]);

  // 平行线不能倒圆
  if (!slope_1 && !slope_2) {
    bus.send<qbe::UiMessage::OperatorInfoMessage>(qbe::UiMessage::OperatorInfoMessage{QObject::tr("mode: fillet | Invalid object")});
    return;
  }
  if (slope_1 && slope_2) {
    if (abs(*slope_1 - *slope_2) < 10e-7) {
      bus.send<qbe::UiMessage::OperatorInfoMessage>(qbe::UiMessage::OperatorInfoMessage{QObject::tr("mode: fillet | Invalid object")});
      return;
    }
  }

  qlib::Vec2d inter_point;
  bool is_Inter;
  std::vector<qlib::Vec2d> seg;
  sortInputPoints(query, input, inter_point, seg, is_Inter);
  double ang =
      auxiliary::angle(auxiliary::point(inter_point.x, inter_point.y), auxiliary::point(seg[0].x, seg[0].y), auxiliary::point(seg[2].x, seg[2].y));
  qlib::Vec2d start_line_dir;
  qlib::Vec2d end_line_dir;

  if (ang < 0) {
    start_line_dir = seg[0] - inter_point;
    end_line_dir = seg[2] - inter_point;
  } else {
    start_line_dir = seg[2] - inter_point;
    end_line_dir = seg[0] - inter_point;
  }
  double start_line_lengh, end_line_lengh;
  start_line_lengh = start_line_dir.length();
  end_line_lengh = end_line_dir.length();

  start_line_dir.normalize();
  end_line_dir.normalize();

  //求切点
  double l = r / tan(abs(ang) / 2);  //交点到起始切点距离
  qlib::Vec2d start_tan_point, end_tan_point;
  start_tan_point.x = inter_point.x + start_line_dir.x * l;
  start_tan_point.y = inter_point.y + start_line_dir.y * l;

  end_tan_point.x = inter_point.x + end_line_dir.x * l;
  end_tan_point.y = inter_point.y + end_line_dir.y * l;

  //判断切点是否超过线段中点,折线模式不能倒圆
  if (param.is_segment_mode == false) {}
  if (l > start_line_lengh / 2 || l > end_line_lengh / 2) {
    bus.send<qbe::UiMessage::OperatorInfoMessage>(qbe::UiMessage::OperatorInfoMessage{QObject::tr("mode: fillet | The radius is too large")});
    return;
  }

  //判断是否可以倒角
  {
    double start_tan_lengh, end_tan_lengh;
    start_tan_lengh = (start_tan_point - inter_point).length();
    end_tan_lengh = (end_tan_point - inter_point).length();
    //判断切点是否超出线段最远的端点
    if (start_tan_lengh > start_line_lengh || end_tan_lengh > end_line_lengh) {
      bus.send<qbe::UiMessage::OperatorInfoMessage>(qbe::UiMessage::OperatorInfoMessage{QObject::tr("mode: fillet | The radius is too large")});
      return;
    }
    if (param.is_segment_mode == true)
      bus.send<qbe::UiMessage::OperatorInfoMessage>(qbe::UiMessage::OperatorInfoMessage{
          QString(QObject::tr("mode: fillet | Select second object (%1; R=%2)")).arg(param.trimString()).arg(QString::number(param.r, 'f', 3))});
  }

  //处理线段延伸
  if (is_Inter == false) {
    {
      qlib::Vec2d tan_point;
      if (ang < 0) {
        tan_point = start_tan_point;
      } else {
        tan_point = end_tan_point;
      }
      double dis_1 = (input[0] - tan_point).length();
      double dis_2 = (input[1] - tan_point).length();
      double dis = (input[0] - input[1]).length();
      if (abs(dis - dis_1 - dis_2) > 10e-5) {
        //切点不在该线段内部，需要延伸到切点处
        /*auto line = std::make_shared<GdsFlexpath>(
            std::vector<Vec2>{Vec2{tan_point[0], tan_point[1]}, Vec2{input[line_1_no_use_point_index][0], input[line_1_no_use_point_index][1]}},
            std::vector<double>{0}, std::vector<double>{0}, std::vector<JoinType>{JoinType::Natural}, std::vector<EndType>{EndType::Flush},
            std::vector<double>{0}, std::vector<uint32_t>{0}, std::vector<uint32_t>{0}, 1e-2, true);*/
        auto line = std::make_shared<qlib::Path>();
        line->spine.points = std::vector<qlib::Vec2d>{
            qlib::Vec2d{tan_point.x, tan_point.y}, qlib::Vec2d{input[param.line_1_no_use_point_index].x, input[param.line_1_no_use_point_index].y}};
        param.extend_lines.push_back(line);
      }
    }

    {
      qlib::Vec2d tan_point;
      if (ang < 0) {
        tan_point = end_tan_point;
      } else {
        tan_point = start_tan_point;
      }
      double dis_1 = (input[2] - tan_point).length();
      double dis_2 = (input[3] - tan_point).length();
      double dis = (input[2] - input[3]).length();
      if (abs(dis - dis_1 - dis_2) > 10e-5) {
        //切点不在该线段内部，需要延伸到切点处
        //auto line = std::make_shared<GdsFlexpath>(
        //    std::vector<Vec2>{Vec2{tan_point[0], tan_point[1]}, Vec2{input[line_2_no_use_point_index][0], input[line_2_no_use_point_index][1]}},
        //    std::vector<double>{0}, std::vector<double>{0}, std::vector<JoinType>{JoinType::Natural}, std::vector<EndType>{EndType::Flush},
        //    std::vector<double>{0}, std::vector<uint32_t>{0}, std::vector<uint32_t>{0}, 1e-2, true);

        auto line = std::make_shared<qlib::Path>();
        line->spine.points = std::vector<qlib::Vec2d>{
            qlib::Vec2d{tan_point.x, tan_point.y}, qlib::Vec2d{input[param.line_2_no_use_point_index].x, input[param.line_2_no_use_point_index].y}};

        param.extend_lines.push_back(line);
      }
    }
  }

  qlib::Vec2d start_to_center_dir;
  start_to_center_dir.x = start_line_dir.y;
  start_to_center_dir.y = -start_line_dir.x;

  qlib::Vec2d center;
  center.x = start_tan_point.x + start_to_center_dir.x * r;
  center.y = start_tan_point.y + start_to_center_dir.y * r;

  double fillet_ang = M_PI - abs(ang);

  //生成圆弧
  auto fan = std::make_shared<Arc>(qlib::Vec2(center.x, center.y), qlib::Vec2(start_tan_point.x, start_tan_point.y), fillet_ang);
  /*qlib::Vec2d cha = qlib::Vec2(start_tan_point.x, start_tan_point.y) - qlib::Vec2(center.x, center.y);
  double angle = atan2(cha.y, cha.x);
  double rad = cha.length();
  auto fan = std::make_shared<qlib::Fan>(qlib::Vec2(center.x, center.y), rad, qlib::Vec2d(angle, angle + fillet_ang), 0);*/
  param.arcs.push_back(fan);

  if (ang < 0) {
    param.arc_dir.push_back(true);
  } else {
    param.arc_dir.push_back(false);
  }
}

Arc::Arc(const qlib::Vec2d& center, const qlib::Vec2d& start_point, double central_angle) {
  m_center = center;
  m_start_point = start_point;
  m_central_angle = central_angle;
}

std::vector<qlib::Vec2d> Arc::make_arc() {
  std::vector<qlib::Vec2d> result;
  qlib::Vec2d dir = m_start_point - m_center;
  double radius = dir.length();
  double star_angle = dir.angle();
  for (uint64_t i = 0; i < m_max_points; i++) {
    const double angle = star_angle + i * m_central_angle / (m_max_points - 1);
    auto v = m_center + qlib::Vec2d{radius * cos(angle), radius * sin(angle)};
    result.push_back(v);
  }
  return result;
}
}  // namespace qbe::FilletTool